package cn.sylinx.horm.resource.parse;

import java.util.Map;

import cn.sylinx.horm.config.ParseSqlType;
import cn.sylinx.horm.dialect.DbType;
import cn.sylinx.horm.exception.HORMException;
import cn.sylinx.horm.resource.ClasspathSqlResource;
import cn.sylinx.horm.resource.ReadableClasspathSqlResourceManager;
import cn.sylinx.horm.util.Pair;
import cn.sylinx.horm.util.StrKit;

class SystemSqlParser extends SqlParser {

    // 数据库类型，用来解析不同数据库类型的sql resource
    private DbType dbtype;
    private String sqlPostfix;

    public SystemSqlParser(String sqlPostfix, DbType dbtype) {
        this.sqlPostfix = sqlPostfix;
        this.dbtype = dbtype;
    }

    public DbType getDbtype() {
        return dbtype;
    }

    public void setDbtype(DbType dbtype) {
        this.dbtype = dbtype;
    }

    public String getSqlPostfix() {
        return sqlPostfix;
    }

    public void setSqlPostfix(String sqlPostfix) {
        this.sqlPostfix = sqlPostfix;
    }

    public Pair parseSql(ClasspathSqlResource sqlResource, Map<String, Object> params) {
        String statement = getRealStatment(sqlResource.getSqlpath());
        return parseSqlUseKey(sqlResource.getSqlpath(), statement, params);
    }

    @Override
    public String parseSqlPart(ClasspathSqlResource sqlResource, Map<String, Object> params) {
        String statement = getRealStatment(sqlResource.getSqlpath());
        return parseSqlPart(statement, ParseSqlType.SYSTEM.getType(), params);
    }

    /**
     * 获取sql文件内容，可能包含#INCLUDE标签
     * 
     * @param sqlpath
     * @return
     */
    protected String getStatement(String sqlpath) {
        String truelySqlPath = parseTruelySqlpath(sqlpath);
        String statement = ReadableClasspathSqlResourceManager.getStatement(truelySqlPath);
        if (StrKit.isBlank(statement)) {
            throw new HORMException("SQL语句为空, 资源:" + truelySqlPath);
        }
        return statement;
    }

    /**
     * 获取真实sql文件内容
     * 
     * @param sqlpath
     * @return
     */
    protected String getRealStatment(String sqlpath) {
        return getStatement(sqlpath);
    }

    protected String getRealSqlPostfix() {
        return "_" + dbtype.getValue() + sqlPostfix;
    }

    protected String parseTruelySqlpath(String sqlpath) {

        if (dbtype == null) {
            return sqlpath;
        }

        // 开启了数据库类型区分
        String dbtypePostfix = getRealSqlPostfix();
        boolean endsWithDbtypePostfix = sqlpath.endsWith(dbtypePostfix);
        if (endsWithDbtypePostfix) {
            return sqlpath;
        }

        int index = sqlpath.lastIndexOf(sqlPostfix);
        if (index < 1) {
            throw new HORMException("invalid sql resource file");
        }

        return sqlpath.substring(0, index) + dbtypePostfix;
    }

    private Pair parseSqlUseKey(String key, String statement, Map<String, Object> params) {
        return new SqlLexerBasedParser(key, statement).apply(params);
    }

    public Pair parseSql(String statement, String type, Map<String, Object> params) {
        return parseSqlUseKey(null, statement, params);
    }

    @Override
    public String parseSqlPart(String statement, String type, Map<String, Object> params) {
        return parseSql(statement, type, params).getFirst();
    }

}